package com.shujia

object Code17Trait {
  def main(args: Array[String]): Unit = {

    /**
     * Scala特质：
     * ① 特质使用trait进行标记，类似于Java中的接口，但是可以存在有具体的实现方法
     * ② 特质使用extends进行继承，如果存在有class也被继承，那么格式要求为  extends class类 with trait名
     * ③ 特质可以实现多继承，并且使用with进行拼接
     * ④ 可以给一个对象动态混入一个特质trait 格式为： new 类() with 特质名
     * ⑤ 特质中可以定义属性，并可以赋值
     * ⑥ 对于重写方法，如果多个特质中存在有相同方法，并重写了，那么在extends继承时，后添加的会覆盖先添加的
     * ⑦ 特质中可以存在抽象方法，在继承时，可以对抽象方法进行实现
     * ⑧ 在特质中也可以存在有抽象的属性，在继承时，需要对该属性进行重写
     *
     */

    val mysql = new Mysql()
    mysql.getConnection()
    mysql.printLog()


    val mysql2 = new Mysql() with OtherPlugin
    mysql2.plugin()
    mysql2.getHiveConnection().getHiveCon()
    mysql2.setHiveConnection()
    // 属性
    mysql2.hiveCon.getHiveCon()

    mysql.exeSQL(
      """
        |select * from emp
        |""".stripMargin)

  }
}

trait ConnectionTrait extends Logger {

  def getConnection(): Unit = {
    println("获取到Mysql连接")
  }

  override def printLog(): Unit = {
    println("连接过程中可以打印日志了....")
  }
}

class Database {

  println("这是一个数据库的顶级父类 ")
}

trait Logger {
  def printLog(): Unit = {
    println("可以获取日志...")
  }
}


trait MySQLLogger extends Logger {
  var value:String

  override def printLog(): Unit = {
    println("Mysql执行过程中可以打印日志了....")
  }

}


trait OtherPlugin {
  var hiveCon: HiveConnection = _


  def plugin(): Unit = {
    println("这是一个万能插件...")
  }

  def getHiveConnection(): HiveConnection = {
    new HiveConnection()
  }

  def setHiveConnection(): Unit = {
    hiveCon = new HiveConnection()
  }

}


class HiveConnection {
  def getHiveCon(): Unit = {
    println("可以连接Hive...")
  }
}


/**
 *
 * Logger
 * -> MySQLLogger printLog
 * -> Connection  printLog
 * -> Mysql  printLog ?
 *
 *
 */
trait ExeSQL {

  // 当前函数没有方法体 -> 抽象函数
  def exeSQL(sql: String): Unit
}

class Mysql extends Database with MySQLLogger with ConnectionTrait with ExeSQL {

  var user: String = _
  var password: String = _

  override def exeSQL(sql: String): Unit = {
    println("Mysql执行了SQL语句：" + sql)
  }

  override var value: String = _
}